﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Kugar.Core.ExtMethod;
using Kugar.Core.Web;
using Microsoft.AspNetCore.Http;

namespace Kugar.Tool.Web.RequestFieldValidation
{
    public class RequestArrayField<TItem> :IRequestArrayField<IEnumerable<TItem>, TItem>
    {
        private List<IRule> _rules = new List<IRule>();
        
        private HttpRequest _request = null;
        private TItem[] _inputValue;
        private IRequestArrayElementField<TItem>[] _valueFields = null;
        private Func<int,string> _nameBuilder = null;

        internal RequestArrayField(string fieldName, TItem[] inputValue, HttpRequest request, string title)
        {
            Request = request;
            FieldName = fieldName;

            Title =title.IfEmptyOrWhileSpace(fieldName);

            _inputValue = inputValue;

            if (_inputValue.HasData())
            {
                var lst = new List<ArrayElementField<TItem>>(_inputValue.Length);

                for (int i = 0; i < inputValue.Length; i++)
                {
                    lst.Add(new ArrayElementField<TItem>(this, i));
                }

                _valueFields = lst.ToArrayEx();
            }

            StringValue = request.GetString(fieldName, null);

            //ElementFieldNameTemplate = $"{fieldName}_第[{{0}}]行";
            //ElementTitleTemplate = $"{title}_第[{{0}}]行";
        }


        /// <summary>
        /// 重新设置值,可用于对数组值进行再次过滤处理,处理后的值,将替换原有的值,如手动过滤空值等操作
        /// </summary>
        /// <param name="castFunc">转换函数</param>
        /// <returns></returns>
        public IRequestArrayField<IEnumerable<TItem>, TItem> ResetValues(Func<IEnumerable<TItem>, IEnumerable<TItem>> castFunc)
        {
            _inputValue = castFunc(_inputValue).ToArrayEx();

            var lst = new List<ArrayElementField<TItem>>(_inputValue.Length);

            for (int i = 0; i < _inputValue.Length; i++)
            {
                lst.Add(new ArrayElementField<TItem>(this, i));
            }

            _valueFields = lst.ToArrayEx();

            return this;
        }

        public TItem[] Value()
        {
            return _inputValue;
        }


        public string StringValue { get; }
        public IEnumerable<IRule> Rules => _rules;

        public bool IsValid
        {
            get
            {
                foreach (var rule in _rules)
                {
                    var ret = rule.Validate(this);

                    if (!ret)
                    {
                        return false;
                    }
                }

                foreach (var field in _valueFields)
                {
                    if (!field.IsValid)
                    {
                        return false;
                    }
                    //foreach (var rule in field.Rules)
                    //{
                    //    if (!rule.Validate(field))
                    //    {
                    //        return false;
                    //    }
                    //}
                }

                return true;
            }
        }

        public HttpRequest Request { get; }

        public void AddRule(IRule rule)
        {
            _rules.Add(rule);
        }

        public string FieldName { get; }

        public string Title { get; }

        public string Format { get; }

        public IRequestArrayElementField<TItem>[] ElementFields => _valueFields;

        public static RequestArrayField<TArrayElement> FromValue<TArrayElement>(string fieldName, TArrayElement[] inputValue,
            HttpRequest request = null, string title = "")
        {
            return new RequestArrayField<TArrayElement>(fieldName,inputValue,request??Kugar.Core.Web.HttpContext.Current.Request,title);
            ;
        }

        public IRequestArrayField<IEnumerable<TItem>, TItem> WithElement(ArrayFieldCheckElementWithIndex<TItem> checkFunc)
        {
            for (int i = 0; i < _inputValue.Length; i++)
            {
                checkFunc(i, this.ElementFields[i]);
            }

            return this;
        }

        public IRequestArrayField<IEnumerable<TItem>, TItem> WithElementNameBuilder(Func<int, string> nameBuilder)
        {
            _nameBuilder = nameBuilder;

            return this;
        }
        
        public IRequestArrayField<IEnumerable<TItem>, TItem> WithElement(ArrayFieldCheckElement<TItem> checkFunc)
        {
            return WithElement((index, field) => checkFunc(field));
        }

        public class ArrayElementField<TInputElement> : IRequestArrayElementField<TInputElement>
        {
            private RequestArrayField<TInputElement> _arrayField = null;
            private List<IRule> _elementRules = new List<IRule>();
            private int _index = -1;
            private string _elementName = "";

            public ArrayElementField(RequestArrayField<TInputElement> arrayField, int index)
            {
                _arrayField = arrayField;
                _index = index;
                _elementName = arrayField.FieldName;
                
            }

            public TInputElement Value()
            {
                return _arrayField.Value()[_index];
            }

            public IRequestArrayElementField<TInputElement> ElementFieldName(string fieldName)
            {
                if (string.IsNullOrWhiteSpace(fieldName))
                {
                    _elementName = fieldName;
                }

                return this;
            }

            public string StringValue => _arrayField.Value()[_index].ToStringEx();

            public IEnumerable<IRule> Rules => _elementRules; 

            public bool IsValid 
            {
                get
                {
                    foreach (var rule in _elementRules)
                    {
                        if (!rule.Validate(_arrayField.ElementFields[_index]))
                        {
                            return false;
                        }
                    }

                    return true;
                }
            }

            public HttpRequest Request => _arrayField.Request;

            public void AddRule(IRule rule)
            {
                _elementRules.Add(rule);
            }

            public string FieldName => _elementName;

            public string Title { get; }

            public string Format { get; }
        }

        //public IEnumerable<IRule> ElementRules => _elementRules;
    }

        
    /// <summary>
    /// 带索引序号的子元素校验函数
    /// </summary>
    /// <typeparam name="TValue"></typeparam>
    /// <param name="index"></param>
    /// <param name="field"></param>
    public delegate void ArrayFieldCheckElementWithIndex<TValue>(int index, IRequestField<TValue> field);

    /// <summary>
    /// 不带索引序号的子元素校验函数
    /// </summary>
    /// <typeparam name="TValue"></typeparam>
    /// <param name="field"></param>
    public delegate void ArrayFieldCheckElement<TValue>(IRequestField<TValue> field);
}
